home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / share / perl5 / Mail / Mailer.pm < prev    next >
Text File  |  2008-04-14  |  5KB  |  208 lines

  1. # Copyrights 1995-2008 by Mark Overmeer <perl@overmeer.net>.
  2. #  For other contributors see ChangeLog.
  3. # See the manual pages for details on the licensing terms.
  4. # Pod stripped from pm file by OODoc 1.04.
  5. use strict;
  6.  
  7. package Mail::Mailer;
  8. use vars '$VERSION';
  9. $VERSION = '2.03';
  10. use base 'IO::Handle';
  11.  
  12. use POSIX qw/_exit/;
  13.  
  14. use Carp;
  15. use Config;
  16.  
  17.  
  18.  
  19. sub is_exe($);
  20.  
  21. sub Version { our $VERSION }
  22.  
  23. our @Mailers =
  24.   ( sendmail => '/usr/lib/sendmail;/usr/sbin/sendmail;/usr/ucblib/sendmail'
  25.   , smtp     => undef
  26.   , qmail    => '/usr/sbin/qmail-inject;/var/qmail/bin/qmail-inject'
  27.   , testfile => undef
  28.   );
  29.  
  30. push @Mailers, map { split /\:/, $_, 2 }
  31.                    split /$Config{path_sep}/, $ENV{PERL_MAILERS}
  32.     if $ENV{PERL_MAILERS};
  33.  
  34. our %Mailers = @Mailers;
  35. our $MailerType;
  36. our $MailerBinary;
  37.  
  38. # does this really need to be done? or should a default mailer be specfied?
  39.  
  40. $Mailers{sendmail} = 'sendmail'
  41.     if $^O eq 'os2' && ! is_exe $Mailers{sendmail};
  42.  
  43. if($^O =~ m/^ (?: MacOS|VMS|MSWin|os2|NetWare ) $/x )
  44. {   $MailerType   = 'smtp';
  45.     $MailerBinary = $Mailers{$MailerType};
  46. }
  47. else
  48. {   for(my $i = 0 ; $i < @Mailers ; $i += 2)
  49.     {   $MailerType = $Mailers[$i];
  50.         if(my $binary = is_exe $Mailers{$MailerType})
  51.         {   $MailerBinary = $binary;
  52.             last;
  53.         }
  54.     }
  55. }
  56.  
  57. sub import
  58. {   shift;  # class
  59.     @_ or return;
  60.  
  61.     my $type = shift;
  62.     my $exe  = shift || $Mailers{$type};
  63.  
  64.     is_exe $exe
  65.         or carp "Cannot locate '$exe'";
  66.  
  67.     $MailerType = $type;
  68.     $Mailers{$MailerType} = $exe;
  69. }
  70.  
  71. sub to_array($)
  72. {   my ($self, $thing) = @_;
  73.     ref $thing ? @$thing : $thing;
  74. }
  75.  
  76. sub is_exe($)
  77. {   my $exe = shift || '';
  78.  
  79.     foreach my $cmd (split /\;/, $exe)
  80.     {   $cmd =~ s/^\s+//;
  81.  
  82.         # remove any options
  83.         my $name = ($cmd =~ /^(\S+)/)[0];
  84.  
  85.         # check for absolute or relative path
  86.         return $cmd
  87.             if -x $name && ! -d $name && $name =~ m![\\/]!;
  88.  
  89.         if(defined $ENV{PATH})
  90.         {   foreach my $dir (split /$Config{path_sep}/, $ENV{PATH})
  91.             {   return "$dir/$cmd"
  92.                 if -x "$dir/$name" && ! -d "$dir/$name";
  93.             }
  94.         }
  95.     }
  96.     0;
  97. }
  98.  
  99.  
  100. sub new($@)
  101. {   my ($class, $type, @args) = @_;
  102.  
  103.     $type ||= $MailerType
  104.           ||  croak "No MailerType specified";
  105.  
  106.     my $exe = $Mailers{$type};
  107.  
  108.     if(defined $exe)
  109.     {   $exe   = is_exe $exe
  110.             if defined $type;
  111.  
  112.         $exe ||= $MailerBinary
  113.              ||  croak "No mailer type specified (and no default available), thus can not find executable program.";
  114.     }
  115.  
  116.     $class = "Mail::Mailer::$type";
  117.     eval "require $class" or die $@;
  118.  
  119.     my $glob = $class->SUPER::new;   # object is a GLOB!
  120.     %{*$glob} = (Exe => $exe, Args => [ @args ]);
  121.     $glob;
  122. }
  123.  
  124.  
  125. sub open($)
  126. {   my ($self, $hdrs) = @_;
  127.     my $exe    = *$self->{Exe};   # no exe, then direct smtp
  128.     my $args   = *$self->{Args};
  129.  
  130.     my @to     = $self->who_to($hdrs);
  131.     my $sender = $self->who_sender($hdrs);
  132.     
  133.     $self->close;    # just in case;
  134.  
  135.     if(defined $exe)
  136.     {   # Fork and start a mailer
  137.         my $child = open $self, '|-';
  138.         defined $child or die "Failed to send: $!";
  139.  
  140.         if($child==0)
  141.         {   # Child process will handle sending, but this is not real exec()
  142.             # this is a setup!!!
  143.             unless($self->exec($exe, $args, \@to, $sender))
  144.             {   warn $!;     # setup failed
  145.                 _exit(1);    # no DESTROY(), keep it for parent
  146.             }
  147.         }
  148.     }
  149.     else
  150.     {   $self->exec($exe, $args, \@to, $sender)
  151.             or die $!;
  152.     }
  153.  
  154.     $self->set_headers($hdrs);
  155.     $self;
  156. }
  157.  
  158. sub _cleanup_hdrs($)
  159. {   foreach my $h (values %{(shift)})
  160.     {   foreach (ref $h ? @$h : $h)
  161.         {   s/\n\s*/ /g;
  162.             s/\s+$//;
  163.         }
  164.     }
  165. }
  166.  
  167. sub exec($$$$)
  168. {   my($self, $exe, $args, $to, $sender) = @_;
  169.  
  170.     # Fork and exec the mailer (no shell involved to avoid risks)
  171.     my @exe = split /\s+/, $exe;
  172.     exec @exe, @$args, @$to;
  173. }
  174.  
  175. sub can_cc { 1 }    # overridden in subclass for mailer that can't
  176.  
  177. sub who_to($)
  178. {   my($self, $hdrs) = @_;
  179.     my @to = $self->to_array($hdrs->{To});
  180.     unless($self->can_cc)  # Can't cc/bcc so add them to @to
  181.     {   push @to, $self->to_array($hdrs->{Cc} ) if $hdrs->{Cc};
  182.         push @to, $self->to_array($hdrs->{Bcc}) if $hdrs->{Bcc};
  183.     }
  184.     @to;
  185. }
  186.  
  187. sub who_sender($)
  188. {   my ($self, $hdrs) = @_;
  189.     ($self->to_array($hdrs->{Sender} || $hdrs->{From}))[0];
  190. }
  191.  
  192. sub epilogue {
  193.     # This could send a .signature, also see ::smtp subclass
  194. }
  195.  
  196. sub close(@)
  197. {   my $self = shift;
  198.     fileno $self or return;
  199.  
  200.     $self->epilogue;
  201.     CORE::close $self;
  202. }
  203.  
  204. sub DESTROY { shift->close }
  205.  
  206.  
  207. 1;
  208.